package com.sky.utils;

import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.CaseFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;

/**
 * 分页工具类，用于根据给定的查询条件和实体类，动态生成查询Wrapper，实现分页查询。
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageUtils<T> {

    /**
     * 当前页的页码
     * 页码从1开始计数。
     */
    private Long pageNum;

    /**
     * 每页显示的记录数
     */
    private Long pageSize;

    /**
     * 总记录数
     * 用于计算总页数。
     */
    private Long total;

    /**
     * 当前页的记录列表
     */
    private List<T> records;



    /**
     * 根据查询条件、实体类和分页信息，动态生成查询Wrapper，执行分页查询。
     *
     * @param baseMapper 基础Mapper接口，用于执行数据库查询操作。
     * @param clazz 泛型类型。
     * @param vo 实体类对象，用于从其中提取字段信息作为查询条件。
     * @return 返回分页查询结果。
     * @param <T> 数据库实体类类型。
     * @param <U> 分页参数对象类型。
     */
    public static <T,U> PageUtils selectPage(BaseMapper<T> baseMapper, U vo, Class<T> clazz) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();

        // 获取实体类和分页参数对象的所有字段
        Field[] declaredFields = clazz.getDeclaredFields();
        Field[] paramDeclaredFields = vo.getClass().getDeclaredFields();

        // 遍历实体类字段，与分页参数对象字段匹配，设置查询条件
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            // 属性名称
            String declaredFieldName = declaredField.getName();
            for (Field paramDeclaredField : paramDeclaredFields) {
                paramDeclaredField.setAccessible(true);
                if (declaredFieldName.equals(paramDeclaredField.getName())) {
                    try {
                        // 属性值
                        Object value = paramDeclaredField.get(vo);
                        if (value != null) {
                            // 根据字段名转换为数据库列名格式
                            // 获取db columnName
                            String column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, declaredFieldName);
                            // 根据字段值类型设置查询条件
                            // bugfix 修复删除的查询
                            if (value instanceof String) {
                                queryWrapper.like(column, value);
                            } else {
                                queryWrapper.eq(column, value);
                            }
                            if (value instanceof Collection) {
                                Collection<?> collection = (Collection<?>) value;
                                queryWrapper.in(collection.size() > 0, column, collection);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

            // 处理逻辑删除字段
            TableLogic tableLogic = declaredField.getAnnotation(TableLogic.class);
            if (tableLogic != null){
                String delval = tableLogic.delval();
                if (StringUtils.isEmpty(delval)){
                    delval = "1";
                }

                // 获取db columnName
                String column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, declaredFieldName);

                // 必带的条件
                queryWrapper.eq(column, delval);
            }
        }

        // 从ThreadLocal中获取分页参数
        Long pageNum = ThreadLocalUtils.pageNumThreadLocal.get();
        ThreadLocalUtils.pageNumThreadLocal.remove();
        Long pageSize = ThreadLocalUtils.pageSizeThreadLocal.get();
        ThreadLocalUtils.pageSizeThreadLocal.remove();

        // 创建分页对象
        // 分页对象
        Page<T> pageParam = new Page<>(pageNum, pageSize);

        // 执行分页查询
        IPage<T> page = baseMapper.selectPage(pageParam, queryWrapper);

        PageUtils<T> pageUtils = new PageUtils<>(pageNum, pageSize, page.getTotal(), page.getRecords());

        return pageUtils;
    }

    public static <T> PageUtils selectPage(BaseMapper<T> baseMapper, LambdaQueryWrapper<T> queryWrapper) {
        // 从ThreadLocal中获取分页参数
        Long pageNum = ThreadLocalUtils.pageNumThreadLocal.get();
        ThreadLocalUtils.pageNumThreadLocal.remove();
        Long pageSize = ThreadLocalUtils.pageSizeThreadLocal.get();
        ThreadLocalUtils.pageSizeThreadLocal.remove();

        // 创建分页对象
        // 分页对象
        Page<T> pageParam = new Page<>(pageNum, pageSize);

        // 执行分页查询
        IPage<T> page = baseMapper.selectPage(pageParam, queryWrapper);

        PageUtils<T> pageUtils = new PageUtils<>(pageNum, pageSize, page.getTotal(), page.getRecords());

        return pageUtils;
    }
}
